package com.ug.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ug.common.id.SnowFlakeFactory;
import com.ug.common.utils.*;
import com.ug.logs.annotation.Log;
import com.ug.system.entity.SysOperLog;
import com.ug.system.entity.SysLoginLog;
import com.ug.system.entity.dto.QueryDto;
import com.ug.system.entity.dto.SysOperLogDto;
import com.ug.system.mapper.SysOperLogMapper;
import com.ug.system.service.SysOperLogService;
import com.ug.system.service.SysLoginLogService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Author LY
 * @create 2024/7/16 17:44
 * @Description 日志服务实现层
 */
@Service
@RequiredArgsConstructor
public class SysOperLogServiceImpl extends ServiceImpl<SysOperLogMapper, SysOperLog> implements SysOperLogService {

    private static final Logger logger = LoggerFactory.getLogger(SysOperLogServiceImpl.class);

    private static final String LOGIN_PATH = "login";
    private static final String QUICK_LOGIN_PATH = "quickLogin";

    private final SysLoginLogService sysLoginLogService;

    @Override
    public void save(String username, ProceedingJoinPoint joinPoint, SysOperLog sysOperLog) {
        //  请求对象
        HttpServletRequest request = RequestHolder.getHttpServletRequest();
        //  方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //  获取方法名
        Method method = signature.getMethod();
        //  获取Log注解
        Log aopLog = method.getAnnotation(Log.class);

        //  方法路径
        String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";

        StringBuilder params = new StringBuilder("{");
        //  参数值
        List<Object> argValues = new ArrayList<>(Arrays.asList(joinPoint.getArgs()));
        //  参数名称
        for (Object argValue : argValues) {
            params.append(argValue).append(" ");
        }
        //  描述
        if (sysOperLog != null) {
            sysOperLog.setDescription(aopLog.value());
        }
        assert sysOperLog != null;
        String ip = IpUtils.getIpAddress(request);
        //  请求ip地址
        sysOperLog.setIp(ip);
        //  请求ip归属地
        sysOperLog.setAddress(IpRegionUtil.getInstance().getRegion(ip));
        logger.info("当前请求方法：{}", signature.getName());
        //  如果是登录
        if (StrUtil.equals(LOGIN_PATH, signature.getName()) || StrUtil.equals(QUICK_LOGIN_PATH, signature.getName())) {
            //  保存登录日志
            SysLoginLog loginLog = new SysLoginLog();
            loginLog.setStatus(sysOperLog.getStatus());
            loginLog.setExceptionDetail(sysOperLog.getExceptionDetail());
            loginLog.setDescription(sysOperLog.getDescription());
            sysLoginLogService.saveLoginLog(loginLog);
            return;
        }
        //  操作人id
        sysOperLog.setUserId(JwtUtil.getUserId());
        //  方法名称
        sysOperLog.setMethod(methodName);
        //  操作人名称
        sysOperLog.setUsername(username);
        //  方法参数
        sysOperLog.setParams(params + " }");
        if (sysOperLog.getOperId() == null) {
            sysOperLog.setOperId(SnowFlakeFactory.getSnowFlakeFromCache().nextId());
            baseMapper.insert(sysOperLog);
        } else {
            baseMapper.updateById(sysOperLog);
        }
    }

    @Override
    public IPage<SysOperLog> getLogList(QueryDto queryDto, SysOperLogDto sysOperLogDto) {
        LambdaQueryWrapper<SysOperLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(SysOperLog::getCreateTime);
        if (sysOperLogDto.getStatus() != null){
            wrapper.eq(SysOperLog::getStatus, sysOperLogDto.getStatus());
        }
        if (StringUtil.isNotBlank(sysOperLogDto.getUserName())){
            wrapper.eq(SysOperLog::getUsername, sysOperLogDto.getUserName());
        }
        if (StringUtil.isNotBlank(sysOperLogDto.getDescription())){
            wrapper.eq(SysOperLog::getDescription, sysOperLogDto.getDescription());
        }
        Page<SysOperLog> page = new Page<>();
        page.setSize(queryDto.getSize());
        page.setCurrent(queryDto.getCurrentPage());
        return baseMapper.selectPage(page, wrapper);
    }
}
